package com.cbg.archives.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.cbg.archives.dto.ArchivesModularDTO;
import com.cbg.archives.dto.EsArchivesDTO;
import com.cbg.archives.dto.ModularColDTO;
import com.cbg.archives.entity.EsArchives;
import com.cbg.archives.entity.EsArchivesModular;
import com.cbg.archives.entity.EsArchivesModularCol;
import com.cbg.archives.service.IArchivesService;
import com.cbg.archives.service.IEsArchivesModularColService;
import com.cbg.archives.service.IEsArchivesModularService;
import com.cbg.archives.service.IEsArchivesService;
import com.cbg.archives.vo.ArchivesVO;
import com.cbg.archives.vo.ModularVO;
import com.cbg.dto.DirectionsDTO;
import com.cbg.dto.SelectedColListDTO;
import com.cbg.enums.EsSearchManageExceptionEnum;
import com.cbg.enums.MoveDirectionEnum;
import com.cbg.es.entity.EsCol;
import com.cbg.es.entity.EsTable;
import com.cbg.es.service.IEsColService;
import com.cbg.es.service.IEsTableService;
import com.cbg.utils.CollectionUtils;
import com.cbg.vo.DirectionsVO;
import com.shuyuwl.core.enums.StatusEnum;
import com.shuyuwl.core.exception.SymServiceException;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 个人档案service
 *
 * @author wangjuzheng
 * @date 2019-10-24
 **/
@Service
@Transactional(rollbackFor = SymServiceException.class)
public class ArchivesServiceImpl implements IArchivesService {

    @Resource
    private IEsArchivesModularColService esArchivesModularColService;

    @Resource
    private IEsArchivesModularService esArchivesModularService;

    @Resource
    private IEsArchivesService esArchivesService;

    @Resource
    private IEsTableService tableService;
    @Resource
    private IEsColService esColService;

    @Override
    public List<EsArchivesDTO> getArchivesList() {

        List<EsArchivesDTO> list = new ArrayList<>();
        //获取所有未删除的档案分类信息
        List<EsArchives> esArchivesList = esArchivesService.findAllEsArchivesAndStatus(StatusEnum.OK.getCode());
        if (CollectionUtils.isNotEmpty(esArchivesList)) {
            //获取分类信息
            list = JSONObject.parseArray(JSONObject.toJSONString(esArchivesList), EsArchivesDTO.class);
        }
        return list;
    }

    @Override
    public void updateArchivesDirections(DirectionsVO directionsVO) {

        //分类信息的获取
        List<EsArchives> esArchivesList = esArchivesService.findByPidAndStatus(directionsVO.getPid() == null ? 0L : directionsVO.getPid(), StatusEnum.OK.getCode());
        //该父级分类下没有分类信息
        if (CollectionUtils.isEmpty(esArchivesList)) {
            throw new SymServiceException(EsSearchManageExceptionEnum.CATEGORY_NULL.getCode(), EsSearchManageExceptionEnum.CATEGORY_NULL.getMsg());
        }
        //分类信息的验证
        EsArchives esArchives = checkEsArchives(directionsVO.getId());
        //获取需要移动类的下标
        int currentIndex = esArchivesList.indexOf(esArchives);
        //需要移动的分类不存在
        if (currentIndex == -1) {
            throw new SymServiceException(EsSearchManageExceptionEnum.CATEGORY_INDEX_NULL.getCode(), EsSearchManageExceptionEnum.CATEGORY_INDEX_NULL.getMsg());
        }

        MoveDirectionEnum moveDirectionEnum = MoveDirectionEnum.getDirectionByCode(directionsVO.getDirectionType());
        //分类位置移动
        moveArchivesDirections(currentIndex, esArchives, moveDirectionEnum, esArchivesList);
    }

    /**
     * 档案分类名称的修改
     *
     * @param archivesId 分类id
     * @param name       名称
     */
    @Override
    public EsArchivesDTO updateArchivesName(Long archivesId, String name) {

        //获取档案分类信息
        EsArchives esArchives = checkEsArchives(archivesId);

        //验证分类民名称是否存在
        //根据分类名称查询条数
        List<EsArchives> archivesList = esArchivesService.findByPidAndCategoryName(esArchives.getPid(), name.trim());
        if (CollectionUtils.isNotEmpty(archivesList)) {
            if ((archivesList.size() > 1 || !esArchives.getId().equals(archivesList.get(0).getId()))) {
                throw new SymServiceException(EsSearchManageExceptionEnum.ERROR_CATEGORY_NAME_NOT_NULL.getCode(), EsSearchManageExceptionEnum.ERROR_CATEGORY_NAME_NOT_NULL.getMsg());
            }
        }
        //档案分类名称
        esArchives.setName(name.trim());
        //保存
        esArchivesService.save(esArchives);
        return JSONObject.parseObject(JSONObject.toJSONString(esArchives), EsArchivesDTO.class);
    }

    /**
     * 分类的删除
     *
     * @param archivesId 分类
     */
    @Override
    public void deleteArchives(Long archivesId) {

        //获取档案分类信息
        EsArchives esArchives = checkEsArchives(archivesId);

        //根据档案分类id获取未删除的模块信息
        esArchivesModularService.deleteByArchivesId(archivesId);
        //根据父级id获取所属的分类信息
        List<EsArchives> list = esArchivesService.findByPidAndStatus(archivesId, StatusEnum.OK.getCode());
        if (CollectionUtils.isNotEmpty(list)) {
            list.forEach(esCategory1 -> deleteArchives(esCategory1.getId()));
        }
        //状态
        esArchives.setStatus(StatusEnum.DELETE.getCode());
        //分类的删除
        esArchivesService.save(esArchives);
    }

    @Override
    public EsArchivesDTO addArchives(ArchivesVO archivesVO) {

        if (archivesVO.getPid() != null) {
            //分类信息的验证
            checkEsArchives(archivesVO.getPid());
        }
        //验证分类民名称是否存在
        List<EsArchives> list = esArchivesService.findByPidAndCategoryName(archivesVO.getPid(), archivesVO.getName().trim());
        //分类名称已存在
        if (CollectionUtils.isNotEmpty(list)) {
            throw new SymServiceException(EsSearchManageExceptionEnum.ERROR_CATEGORY_NAME_NOT_NULL.getCode(), EsSearchManageExceptionEnum.ERROR_CATEGORY_NAME_NOT_NULL.getMsg());
        }

        Long pid = archivesVO.getPid() == null ? 0L : archivesVO.getPid();
        EsArchives esArchives = new EsArchives();
        //上级分类ID
        esArchives.setPid(pid);
        //图标
        esArchives.setIcon(archivesVO.getIcon());
        //分类名称
        esArchives.setName(archivesVO.getName().trim());
        //状态
        esArchives.setStatus(StatusEnum.OK.getCode());

        //获取最大的排序号
        Integer sort = esArchivesService.getMaxSort(pid, StatusEnum.OK.getCode());
        //排序
        esArchives.setSort(sort == null ? 1 : sort + 1);
        esArchivesService.save(esArchives);

        return JSONObject.parseObject(JSONObject.toJSONString(esArchives), EsArchivesDTO.class);
    }

    @Override
    public void addModular(ModularVO modularVO) {

        //分类信息的验证
        checkEsArchives(modularVO.getArchivesId());
        //验证表信息
        tableService.checkEsTable(modularVO.getTableId());
        if (modularVO.getId() == null) {
            //验证分类民名称是否存在
            List<EsArchivesModular> list = esArchivesModularService.findByPidAndModularName(modularVO.getArchivesId(), modularVO.getName().trim());
            //模块名称已存在
            if (CollectionUtils.isNotEmpty(list)) {
                throw new SymServiceException(EsSearchManageExceptionEnum.ERROR_MODULAR_NAME_NOT_NULL.getCode(), EsSearchManageExceptionEnum.ERROR_MODULAR_NAME_NOT_NULL.getMsg());
            }
        }
        EsArchivesModular modular = new EsArchivesModular();
        BeanUtils.copyProperties(modularVO, modular);
        //获取最大的排序
        Integer sort = esArchivesModularService.getMaxSort(modularVO.getArchivesId(), StatusEnum.OK.getCode());
        modular.setSort(sort == null ? 1 : sort + 1);
        //分类id
        modular.setArchivesId(modularVO.getArchivesId());
        //状态
        modular.setStatus(StatusEnum.OK.getCode());
        //id
        modular.setId(modularVO.getId());
        esArchivesModularService.save(modular);

        //列的保存
        saveModularColService(modular.getId(), modularVO.getList());
    }

    @Override
    public void deleteModular(Long modularId) {

        EsArchivesModular esArchivesModular = checkEsArchivesModular(modularId);
        //删除模块对应的列
        esArchivesModularColService.deleteByModularId(modularId, StatusEnum.DELETE.getCode());
        //删除模块
        esArchivesModular.setStatus(StatusEnum.DELETE.getCode());
        esArchivesModularService.save(esArchivesModular);
    }

    @Override
    public void updateModular(ModularVO modularVO) {

        //分类信息的验证
        checkEsArchives(modularVO.getArchivesId());
        //当模块id存在时
        EsArchivesModular archivesModular = checkEsArchivesModular(modularVO.getId());
        //验证分类民名称是否存在
        List<EsArchivesModular> archivesModularList = esArchivesModularService.findByPidAndModularName(modularVO.getArchivesId(), modularVO.getName().trim());
        //模块名称已存在
        if (CollectionUtils.isNotEmpty(archivesModularList)) {
            if ((archivesModularList.size() > 1 || !archivesModular.getId().equals(archivesModularList.get(0).getId()))) {
                throw new SymServiceException(EsSearchManageExceptionEnum.ERROR_MODULAR_NAME_NOT_NULL.getCode(), EsSearchManageExceptionEnum.ERROR_MODULAR_NAME_NOT_NULL.getMsg());
            }
        }
        //当保存的表信息之前的则删除以前的
        if (!modularVO.getTableId().equals(archivesModular.getTableId())) {
            esArchivesModularColService.deleteByModularId(archivesModular.getId(), StatusEnum.DELETE.getCode());
        }

        //模块的保存
        addModular(modularVO);
    }

    @Override
    public List<ArchivesModularDTO> getModular(Long archivesId) {

        //分类信息的验证
        checkEsArchives(archivesId);
        return esArchivesModularService.selectedArchives(archivesId);
    }

    @Override
    public List<SelectedColListDTO> selectedModular(Long modularId, Long tableId) {

        //模块验证
        if (modularId != null) {
            EsArchivesModular esArchivesModular = checkEsArchivesModular(modularId);
            if (esArchivesModular.getTableId().equals(tableId)) {
                return esArchivesModularColService.selectedModular(modularId);
            }
        }

        EsTable esTable = tableService.checkEsTable(tableId);
        List<EsCol> list = esColService.findByTableName(esTable.getTableName());
        if (CollectionUtils.isNotEmpty(list)) {
            return list.stream().map(esCol -> {
                SelectedColListDTO esColListDTO = new SelectedColListDTO();
                //显示列ID
                esColListDTO.setColId(esCol.getId());
                //状态
                esColListDTO.setStatus(StatusEnum.OK.getCode());
                //列显示名
                esColListDTO.setColNameAlias(esCol.getColNameAlias());
                //列名
                esColListDTO.setName(esCol.getName());
                //列注释
                esColListDTO.setNameCn(esCol.getNameCn());
                return esColListDTO;
            }).collect(Collectors.toList());
        }
        return new ArrayList<>();
    }

    @Override
    public void updateModularDirections(Long archivesId, Long modularId, Integer directionType) {

        //分类信息的验证
        checkEsArchives(archivesId);
        //根据分类id查询模块信息
        List<DirectionsDTO> list = esArchivesModularService.getDirectionsDTOs(archivesId);
        //该分类下没有模块信息
        if (CollectionUtils.isEmpty(list)) {
            throw new SymServiceException(EsSearchManageExceptionEnum.CATEGORY_MODULAR_NULL.getCode(), EsSearchManageExceptionEnum.CATEGORY_MODULAR_NULL.getMsg());
        }
        //模块信息的验证
        EsArchivesModular modular = checkEsArchivesModular(modularId);
        //获取需要移动类的下标
        List<DirectionsDTO> enableList = list.stream().filter(directionsDTO -> StatusEnum.OK.getCode().equals(directionsDTO.getStatus())).collect(Collectors.toList());
        List<Long> ids = enableList.stream().map(DirectionsDTO::getId).collect(Collectors.toList());
        int currentIndex = ids.indexOf(modular.getId());
        //需要移动的模块不存在
        if (currentIndex == -1) {
            throw new SymServiceException(EsSearchManageExceptionEnum.CATEGORY_MODULAR_MOVE_NULL.getCode(), EsSearchManageExceptionEnum.CATEGORY_MODULAR_MOVE_NULL.getMsg());
        }

        MoveDirectionEnum directionEnum = MoveDirectionEnum.getDirectionByCode(directionType);
        // 请选择正确的移动方向
        if (directionEnum == null) {
            throw new SymServiceException(EsSearchManageExceptionEnum.MOVE_DIRECTION_NULL.getCode(), EsSearchManageExceptionEnum.MOVE_DIRECTION_NULL.getMsg());
        }
        switch (directionEnum) {
            case UP:
                //上移，需要和前一个商品交换下标
                if (currentIndex == 0) {
                    //已经是第一个，无法上移
                    throw new SymServiceException(EsSearchManageExceptionEnum.ERROR_MOVE_DIRECTION_TOP.getCode(), EsSearchManageExceptionEnum.ERROR_MOVE_DIRECTION_TOP.getMsg());
                }
                DirectionsDTO directionsDTO = enableList.get(currentIndex - 1);
                List<Long> modularIds = list.stream().filter(directionsDTO1 -> modular.getSort() > directionsDTO1.getSort()
                        && directionsDTO1.getSort() >= directionsDTO.getSort()).map(DirectionsDTO::getId).collect(Collectors.toList());
                modular.setSort(directionsDTO.getSort());
                esArchivesModularService.save(modular);
                esArchivesModularService.updateSort(modularIds, 1);
                break;
            case DOWN:
                //下移
                if (currentIndex == list.size() - 1) {
                    //已经是最后一个，无法下移
                    throw new SymServiceException(EsSearchManageExceptionEnum.ERROR_MOVE_DIRECTION_DOWN.getCode(), EsSearchManageExceptionEnum.ERROR_MOVE_DIRECTION_DOWN.getMsg());
                }
                DirectionsDTO next = list.get(currentIndex + 1);
                List<Long> modularIds1 = list.stream().filter(directionsDTO1 -> modular.getSort() < directionsDTO1.getSort()
                        && directionsDTO1.getSort() <= next.getSort()).map(DirectionsDTO::getId).collect(Collectors.toList());

                modular.setSort(next.getSort());
                esArchivesModularService.save(modular);
                esArchivesModularService.updateSort(modularIds1, -1);

                break;
            default:
                break;
        }
    }

    /**
     * 个人档案分类位置的移动
     *
     * @param currentIndex  当前页码
     * @param esArchives    个人档案分类信息
     * @param directionEnum 移动枚举
     * @param list          分类信息
     */
    private void moveArchivesDirections(int currentIndex, EsArchives esArchives, MoveDirectionEnum directionEnum,
                                        List<EsArchives> list) {

        // 该分类不存在
        if (directionEnum == null) {
            //请选择正确的移动方向
            throw new SymServiceException(EsSearchManageExceptionEnum.MOVE_DIRECTION_NULL.getCode(), EsSearchManageExceptionEnum.MOVE_DIRECTION_NULL.getMsg());
        }

        switch (directionEnum) {
            case UP:
                //上移，需要和前一个商品交换下标
                if (currentIndex == 0) {
                    //已经是第一个，无法上移
                    throw new SymServiceException(EsSearchManageExceptionEnum.ERROR_MOVE_DIRECTION_TOP.getCode(), EsSearchManageExceptionEnum.ERROR_MOVE_DIRECTION_TOP.getMsg());
                }
                EsArchives previous = list.get(currentIndex - 1);
                previous.setSort(esArchives.getSort() + 1);
                esArchives.setSort(esArchives.getSort() - 1);
                esArchivesService.save(previous);
                esArchivesService.save(esArchives);
                break;
            case DOWN:
                //下移
                if (currentIndex == list.size() - 1) {
                    //已经是最后一个，无法下移
                    throw new SymServiceException(EsSearchManageExceptionEnum.ERROR_MOVE_DIRECTION_DOWN.getCode(), EsSearchManageExceptionEnum.ERROR_MOVE_DIRECTION_DOWN.getMsg());
                }
                EsArchives next = list.get(currentIndex + 1);
                next.setSort(esArchives.getSort() - 1);
                esArchives.setSort(esArchives.getSort() + 1);
                esArchivesService.save(next);
                esArchivesService.save(esArchives);

                break;
            case TOP:
                //置顶
                if (currentIndex == 0) {
                    //已经是第一个，无法上移
                    throw new SymServiceException(EsSearchManageExceptionEnum.ERROR_MOVE_DIRECTION_TOP.getCode(), EsSearchManageExceptionEnum.ERROR_MOVE_DIRECTION_TOP.getMsg());
                }
                esArchives.setSort(list.get(0).getSort());
                esArchivesService.save(esArchives);

                for (int i = 0; i < currentIndex; i++) {
                    EsArchives newEsEsArchives = list.get(i);
                    newEsEsArchives.setSort(newEsEsArchives.getSort() + 1);
                    esArchivesService.save(newEsEsArchives);
                }
                break;
            case LAST:
                //置底
                if (currentIndex == list.size() - 1) {
                    //已经是最后一个，无法下移
                    throw new SymServiceException(EsSearchManageExceptionEnum.ERROR_MOVE_DIRECTION_DOWN.getCode(), EsSearchManageExceptionEnum.ERROR_MOVE_DIRECTION_DOWN.getMsg());
                }
                esArchives.setSort(list.get(list.size() - 1).getSort());
                esArchivesService.save(esArchives);

                for (int i = currentIndex + 1; i < list.size(); i++) {
                    EsArchives newEsEsArchives = list.get(i);
                    newEsEsArchives.setSort(newEsEsArchives.getSort() - 1);
                    esArchivesService.save(newEsEsArchives);
                }
                break;
            default:
                break;
        }
    }

    /**
     * 根据分类id获取分类信息
     *
     * @param archivesId 分类id
     * @return 分类信息
     */
    private EsArchives getArchives(Long archivesId) {

        //分类id不存在
        if (archivesId == null) {
            throw new SymServiceException(EsSearchManageExceptionEnum.ERROR_CATEGORY_ID_NULL.getCode(), EsSearchManageExceptionEnum.ERROR_CATEGORY_ID_NULL.getMsg());
        }

        return esArchivesService.findByIdAndStatus(archivesId, StatusEnum.OK.getCode());
    }

    /**
     * 分类信息的验证
     *
     * @param archivesId 分类id
     * @return 分类详情
     */
    private EsArchives checkEsArchives(Long archivesId) {

        //根据id获取对应的分类详情
        EsArchives esArchives = getArchives(archivesId);
        //分类不存在
        if (esArchives == null) {
            throw new SymServiceException(EsSearchManageExceptionEnum.ERROR_CATEGORY_NULL.getCode(), EsSearchManageExceptionEnum.ERROR_CATEGORY_NULL.getMsg());
        }

        return esArchives;
    }

    /**
     * 根据模块id获取模块信息
     *
     * @param modularId 模块id
     * @return 模块信息
     */
    private EsArchivesModular getEsArchivesModular(Long modularId) {

        //模块id不存在
        if (modularId == null) {
            throw new SymServiceException(EsSearchManageExceptionEnum.ERROR_MODULAR_ID_NULL.getCode(), EsSearchManageExceptionEnum.ERROR_MODULAR_ID_NULL.getMsg());
        }
        return esArchivesModularService.findByIdAndStatus(modularId, StatusEnum.OK.getCode());
    }

    /**
     * 验证模块信息是否存在
     *
     * @param modularId 模块id
     * @return 模块信息
     */
    private EsArchivesModular checkEsArchivesModular(Long modularId) {

        EsArchivesModular esArchivesModular = getEsArchivesModular(modularId);
        //模块信息不存在
        if (esArchivesModular == null) {
            throw new SymServiceException(EsSearchManageExceptionEnum.ERROR_MODULAR_NULL.getCode(), EsSearchManageExceptionEnum.ERROR_MODULAR_NULL.getMsg());
        }
        return esArchivesModular;
    }

    /**
     * 保存模块下的列信息
     *
     * @param modularId 模块id
     * @param list      列信息
     */
    private void saveModularColService(Long modularId, List<ModularColDTO> list) {

        if (CollectionUtils.isNotEmpty(list)) {
            for (int i = 0; i < list.size(); i++) {
                ModularColDTO modularColDTO = list.get(i);
                //修改列
                if (modularColDTO.getId() != null) {
                    EsArchivesModularCol esArchivesModularCol = esArchivesModularColService.findById(modularColDTO.getId());
                    //列名
                    esArchivesModularCol.setColName(modularColDTO.getColNameAlias());
                    //状态
                    esArchivesModularCol.setStatus(modularColDTO.getStatus());
                    //排序
                    esArchivesModularCol.setSort(i);
                    esArchivesModularColService.save(esArchivesModularCol);
                    return;
                }

                //添加列
                EsArchivesModularCol esArchivesModularCol = new EsArchivesModularCol();
                //模块ID
                esArchivesModularCol.setModularId(modularId);
                //显示列ID
                esArchivesModularCol.setColId(modularColDTO.getColId());
                //列名
                esArchivesModularCol.setColName(modularColDTO.getColNameAlias());
                //状态
                esArchivesModularCol.setStatus(modularColDTO.getStatus());
                //排序
                esArchivesModularCol.setSort(i);
                esArchivesModularColService.save(esArchivesModularCol);
            }
        }
    }
}

